/**
 * 新闻管理Hook模块
 * 
 * 本模块提供完整的新闻生命周期管理功能，包括：
 * - 基础新闻CRUD操作（创建、读取、更新、删除）
 * - 草稿箱管理（获取草稿、提交审核）
 * - 审核流程（获取审核列表、执行审核操作）
 * - 发布管理（发布、下线、获取不同状态的新闻）
 * 
 * 该模块使用React Query实现数据获取和缓存管理，提供优化的用户体验：
 * - 自动缓存和重新验证
 * - 乐观更新
 * - 错误处理和用户反馈
 * - 加载状态管理
 * 
 * @module hooks/useNewsManage
 */
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { message } from 'antd';
import { 
  getNewsList, 
  getNewsById, 
  addNews, 
  updateNews, 
  deleteNews,
  submitNews,
  auditNews,
  publishNews,
  unpublishNews,
  getDraftNews,
  getAuditNewsList,
  getAuditNews,
  getUnpublishedNews,
  getPublishedNews,
  getSunsetNews
} from '../api/newsApi';
import { News } from '../types/news';
import { ApiResponse } from '../types/api';
import { STORAGE_KEYS } from '../constants/common';

// 错误类型定义
interface ApiError extends Error {
  response?: {
    status?: number;
    data?: {
      message?: string;
      msg?: string;
      code?: number;
    }
  }
}

// 查询键 - 用于React Query缓存管理
const NEWS_LIST_KEY = 'newsList';          // 新闻列表缓存键
const NEWS_DETAIL_KEY = 'newsDetail';      // 新闻详情缓存键
const DRAFT_NEWS_KEY = 'news.draft';        // 草稿箱缓存键
const AUDIT_LIST_KEY = 'news.auditList';        // 审核列表缓存键
const AUDIT_NEWS_KEY = 'news.audit';        // 待我审核缓存键
const UNPUBLISHED_NEWS_KEY = 'news.unpublished'; // 待发布缓存键
const PUBLISHED_NEWS_KEY = 'news.published';    // 已发布缓存键
const SUNSET_NEWS_KEY = 'news.sunset';          // 已下线缓存键

// ==================== 基础新闻操作 ====================

/**
 * 获取新闻列表Hook
 * 提供新闻列表数据和加载状态
 * 
 * @param {Record<string, string | number | boolean>} params - 查询参数
 * @returns {Object} 包含新闻列表数据和状态的对象
 */
export const useNewsList = (params?: Record<string, string | number | boolean>) => {
  return useQuery({
    queryKey: [NEWS_LIST_KEY, params], // 使用参数作为缓存键的一部分，确保不同参数有不同的缓存
    queryFn: () => getNewsList(params), // 调用API获取新闻列表
  });
};

/**
 * 获取新闻详情Hook
 * 根据ID获取单个新闻的详细信息
 * 
 * @param {number} id - 新闻ID
 * @returns {Object} 包含新闻详情数据和状态的对象
 */
export const useNewsDetail = (id: number) => {
  return useQuery({
    queryKey: [NEWS_DETAIL_KEY, id], // 以ID为缓存键的一部分
    queryFn: async () => {
      const result = await getNewsById(Number(id)); 
      return result as News;
    }, 
    enabled: !!id, // 只有当id存在时，才执行查询
  });
};

/**
 * 添加新闻Hook
 * 处理新闻创建操作
 * 
 * @returns {Object} mutation对象，包含执行方法和状态
 */
export const useAddNews = () => {
  const queryClient = useQueryClient(); // 获取queryClient实例
  
  return useMutation({
    mutationFn: (newsData: Omit<News, 'id'>) => addNews(newsData), // 调用API添加新闻
    onSuccess: () => {
      // 成功后刷新新闻列表和草稿箱
      queryClient.invalidateQueries({ queryKey: [NEWS_LIST_KEY] }); // 使新闻列表缓存失效
      queryClient.invalidateQueries({ queryKey: [DRAFT_NEWS_KEY] }); // 使草稿箱缓存失效
      message.success('新闻添加成功'); // 显示成功消息
    },
    onError: (error: ApiError) => {
      // 显示错误消息，优先使用服务器返回的错误信息
      message.error(error.response?.data?.message || error.message || '添加新闻失败');
    }
  });
};

/**
 * 更新新闻Hook
 * 处理新闻信息更新操作
 * 
 * @returns {Object} mutation对象，包含执行方法和状态
 */
export const useUpdateNews = () => {
  const queryClient = useQueryClient(); // 获取queryClient实例
  
  return useMutation({
    mutationFn: ({ id, data }: { id: number | string, data: Partial<News> }) => 
      updateNews(Number(id), data), // 调用API更新新闻
    onSuccess: (_, variables) => {
      // 成功后刷新新闻详情和列表
      queryClient.invalidateQueries({ queryKey: [NEWS_DETAIL_KEY, variables.id] }); // 使特定新闻详情缓存失效
      queryClient.invalidateQueries({ queryKey: [NEWS_LIST_KEY] }); // 使新闻列表缓存失效
      queryClient.invalidateQueries({ queryKey: [DRAFT_NEWS_KEY] }); // 使草稿箱缓存失效
      message.success('新闻更新成功'); // 显示成功消息
    },
    onError: (error: ApiError) => {
      // 显示错误消息
      message.error(error.response?.data?.message || error.message || '更新新闻失败');
    }
  });
};

/**
 * 删除新闻Hook
 * 处理新闻删除操作
 * 
 * @returns {Object} mutation对象，包含执行方法和状态
 */
export const useDeleteNews = () => {
  const queryClient = useQueryClient(); // 获取queryClient实例
  
  return useMutation({
    mutationFn: (id: number | string) => deleteNews(id), // 调用API删除新闻
    onSuccess: (response: ApiResponse) => {
      // 检查响应是否表示成功
      if (response && (response.code === 200 || response.code === 204)) {
        // 成功后刷新新闻列表和草稿箱
        queryClient.invalidateQueries({ queryKey: [NEWS_LIST_KEY] }); // 使新闻列表缓存失效
        queryClient.invalidateQueries({ queryKey: [DRAFT_NEWS_KEY] }); // 使草稿箱缓存失效
        message.success('新闻删除成功'); // 显示成功消息
      } else {
        // 显示错误消息
        message.error(response?.msg || '删除新闻失败');
      }
    },
    onError: (error: ApiError) => {
      // 显示错误消息
      message.error(error.response?.data?.message || error.message || '删除新闻失败');
    }
  });
};

// ==================== 草稿箱操作 ====================

/**
 * 获取草稿箱新闻列表Hook
 * 获取当前用户的草稿新闻
 * 
 * @param {string} username - 用户名
 * @returns {Object} 包含草稿新闻数据和状态的对象
 */
export const useDraftNews = (username: string) => {
  return useQuery({
    queryKey: [DRAFT_NEWS_KEY, username], // 以用户名为缓存键的一部分
    queryFn: () => getDraftNews(username), // 调用API获取草稿新闻
    enabled: !!username, // 仅在username存在时查询
  });
};

/**
 * 提交新闻审核Hook
 * 将草稿新闻提交审核
 * 
 * @returns {Object} mutation对象，包含执行方法和状态
 */
export const useSubmitNews = () => {
  const queryClient = useQueryClient(); // 获取queryClient实例
  
  return useMutation({
    mutationFn: async (id: number | string) => {
      // 添加详细日志记录
      console.log(`开始提交审核，新闻ID: ${id}，类型: ${typeof id}`);
      
      // 使用本地导入的auth工具而不是context钩子
      const auth = await import('../utils/auth').then(module => module.default);
      console.log(`当前用户信息:`, auth.getUserInfo());
      
      try {
        // 调用API提交新闻审核
        const result = await submitNews(id);
        console.log(`提交审核API调用成功:`, result);
        return result;
      } catch (error) {
        console.error(`提交审核API调用失败:`, error);
        // 重新抛出错误以便上层组件捕获
        throw error;
      }
    },
    onSuccess: (response: ApiResponse, id) => {
      // 检查响应是否表示成功
      if (response && (response.code === 200 || response.code === 201)) {
        // 记录成功日志
        console.log(`提交审核成功，新闻ID: ${id}`);
        
        // 成功后刷新草稿箱和审核列表
        queryClient.invalidateQueries({ queryKey: [DRAFT_NEWS_KEY] }); // 使草稿箱缓存失效
        queryClient.invalidateQueries({ queryKey: [AUDIT_LIST_KEY] }); // 使审核列表缓存失效
        queryClient.invalidateQueries({ queryKey: [AUDIT_NEWS_KEY] }); // 使我的审核列表缓存失效
        queryClient.invalidateQueries({ queryKey: [NEWS_DETAIL_KEY, id] }); // 使新闻详情缓存失效
        
        // 强制刷新审核列表相关查询
        setTimeout(() => {
          queryClient.refetchQueries({ queryKey: [AUDIT_NEWS_KEY] }); 
        }, 300);
        
        message.success('新闻提交审核成功'); // 显示成功消息
      } else {
        // 显示错误消息
        const errorMsg = response?.msg || '提交审核失败，服务器未返回成功状态';
        console.warn(`提交审核API返回非成功状态:`, response);
        message.error(errorMsg);
      }
    },
    onError: (error: Error | ApiError | unknown) => {
      // 详细记录错误信息
      console.error('提交审核失败:', error);
      
      let errorMsg = '提交审核失败，请稍后重试';
      
      if (error instanceof Error) {
        console.error('错误详情:', error.message);
        errorMsg = error.message;
      }
      
      // 处理API错误响应
      const apiError = error as ApiError;
      if (apiError.response?.data) {
        console.error('API响应错误:', apiError.response.data);
        errorMsg = apiError.response.data.msg || 
                   apiError.response.data.message || 
                   errorMsg;
      }
      
      // 显示错误消息
      message.error(errorMsg);
    }
  });
};

// ==================== 审核操作 ====================

/**
 * 获取待审核新闻列表Hook
 * 查询所有待审核状态的新闻
 * 
 * @param {Record<string, unknown>} params - 查询参数
 * @returns {Object} 包含待审核新闻数据和状态的对象
 */
export const useAuditList = (params?: Record<string, unknown>) => {
  return useQuery<News[]>({
    queryKey: [AUDIT_NEWS_KEY, params], // 使用AUDIT_NEWS_KEY作为主缓存键
    queryFn: async () => {
      try {
        // 获取当前用户信息，确保权限检查正确
        const userInfo = localStorage.getItem(STORAGE_KEYS.USER_INFO);
        const user = userInfo ? JSON.parse(userInfo) : null;
        
        // 构建包含角色信息的查询参数
        const auditParams = { 
          ...params,
          roleId: user?.roleId || user?.role?.roleType,
          region: user?.region,
          // 明确指定查询参数
          auditState: 1,
          status: 'pending'
        };
        
        console.log('获取审核列表，查询参数:', auditParams);
        
        // 记录用户信息用于调试
        console.log('当前用户信息:', {
          roleId: user?.roleId,
          region: user?.region,
          username: user?.username
        });
        
        // 使用新的getAuditNews API，它支持参数并内部处理部门隔离
        const result = await getAuditNews(auditParams);
        console.log('获取审核列表成功，数据:', result);
        return result;
      } catch (error) {
        console.error('获取审核列表失败:', error); // 记录错误日志
        
        // 增强错误处理，显示错误详情
        if (error instanceof Error) {
          console.error('错误详情:', error.message);
        }
        
        // 记录API响应错误
        if (error && typeof error === 'object') {
          if ('response' in error) {
            console.error('API响应错误:', error.response);
            // 如果是HTTP错误，展示状态码和响应数据
            const response = (error as ApiError).response;
            if (response) {
              console.error(`HTTP状态码: ${response.status || '未知'}`);
              console.error('响应数据:', response.data || {});
            }
          }
          
          // 检查是否为网络错误
          if ('request' in error && !('response' in error)) {
            console.error('网络错误，请求未收到响应');
          }
          
          // 检查是否有消息属性
          if ('message' in error) {
            console.error('错误消息:', (error as ApiError).message);
          }
        }
        
        return [] as News[]; // 出错时返回空数组
      }
    },
    // 更改缓存和重新获取策略
    staleTime: 5 * 1000, // 5秒内数据视为新鲜
    gcTime: 60 * 1000, // 1分钟后垃圾回收
    refetchOnMount: true, // 组件挂载时重新获取
    refetchOnWindowFocus: true, // 窗口聚焦时重新获取
    // 添加重试逻辑，提高加载成功率
    retry: 2,
    retryDelay: attemptIndex => Math.min(1000 * 2 ** attemptIndex, 10000),
  });
};

/**
 * 获取我的审核列表Hook
 * 获取待当前用户审核的新闻列表
 * 
 * @param {string} username - 用户名
 * @returns {Object} 包含待审核新闻数据和状态的对象
 */
export const useMyAuditList = (username?: string) => {
  return useQuery<News[]>({
    queryKey: [AUDIT_NEWS_KEY, username], // 以用户名为缓存键的一部分
    queryFn: async () => {
      if (!username) {
        return [] as News[]; // 用户名不存在时返回空数组
      }
      try {
        console.log(`正在获取用户 ${username} 的审核列表...`);
        // 使用新的getAuditNewsList API，它支持用户过滤和部门隔离
        const result = await getAuditNewsList(username);
        console.log(`获取用户 ${username} 的审核列表成功，数量:`, result.length);
        return result;
      } catch (error) {
        console.error('获取审核列表失败:', error); // 记录错误日志
        return [] as News[]; // 出错时返回空数组
      }
    },
    enabled: !!username, // 仅在username存在时查询
    staleTime: 10 * 1000, // 10秒内数据被视为新鲜
    gcTime: 5 * 60 * 1000, // 5分钟后垃圾回收缓存
    refetchOnMount: true, // 组件挂载时重新获取
    refetchOnWindowFocus: true, // 窗口聚焦时重新获取
    refetchInterval: 30 * 1000, // 每30秒自动刷新一次
    // 重试策略 - 连续失败时增加重试间隔
    retry: 2, // 失败后重试2次
    retryDelay: attemptIndex => Math.min(1000 * 2 ** attemptIndex, 30000), // 指数退避策略
  });
};

/**
 * 审核新闻Hook
 * 处理新闻审核操作（通过/驳回）
 * 
 * @returns {Object} mutation对象，包含执行方法和状态
 */
export const useAuditNews = () => {
  const queryClient = useQueryClient(); // 获取queryClient实例
  
  return useMutation({
    mutationFn: ({ 
      id, 
      auditState, 
      reason 
    }: { 
      id: number | string, 
      auditState: number, // 审核状态：1=待审核，2=已通过，3=已驳回
      reason?: string // 驳回原因（可选）
    }) => {
      // 获取当前用户信息，确保权限检查正确
      const userInfo = localStorage.getItem(STORAGE_KEYS.USER_INFO);
      const user = userInfo ? JSON.parse(userInfo) : null;
      
      // 构造审核数据，包含用户角色信息
      const auditData = { 
        auditState, 
        reason,
        // 添加用户角色和区域信息，帮助后端识别用户身份
        roleId: user?.roleId || user?.role?.roleType,
        region: user?.region
      };
      
      console.log(`准备审核新闻(ID: ${id})，审核状态: ${auditState}，用户角色: ${auditData.roleId}`);
      
      // 调用API执行审核
      return auditNews(id, auditData);
    },
    onSuccess: () => {
      // 成功后刷新相关列表
      queryClient.invalidateQueries({ queryKey: [AUDIT_LIST_KEY] }); // 使审核列表缓存失效
      queryClient.invalidateQueries({ queryKey: [AUDIT_NEWS_KEY] }); // 使我的审核缓存失效
      queryClient.invalidateQueries({ queryKey: [UNPUBLISHED_NEWS_KEY] }); // 使待发布缓存失效
      message.success('审核操作成功'); // 显示成功消息
    },
    onError: (error: ApiError) => {
      // 显示详细错误信息
      console.error('审核操作失败:', error);
      // 增强错误处理，显示错误详情
      if (error instanceof Error) {
        console.error('错误详情:', error.message);
      }
      if (error && typeof error === 'object' && 'response' in error) {
        console.error('API响应错误:', error.response);
      }
      // 显示错误消息
      message.error(error.response?.data?.message || error.message || '审核操作失败');
    }
  });
};

// ==================== 发布操作 ====================

/**
 * 获取待发布新闻列表Hook
 * 获取已审核通过但未发布的新闻
 * 
 * @param {string} username - 用户名（可选）
 * @returns {Object} 包含待发布新闻数据和状态的对象
 */
export const useUnpublishedNews = (username?: string) => {
  return useQuery({
    queryKey: [UNPUBLISHED_NEWS_KEY, username], // 以用户名为缓存键的一部分
    queryFn: () => getUnpublishedNews(username), // 调用API获取待发布新闻
  });
};

/**
 * 获取已发布新闻列表Hook
 * 获取已发布的新闻
 * 
 * @param {string} username - 用户名（可选）
 * @returns {Object} 包含已发布新闻数据和状态的对象
 */
export const usePublishedNews = (username?: string) => {
  return useQuery({
    queryKey: [PUBLISHED_NEWS_KEY, username], // 以用户名为缓存键的一部分
    queryFn: async () => {
      const result = await getPublishedNews(username);
      return result as News[];
    },
  });
};

/**
 * 获取已下线新闻列表Hook
 * 获取已下线的新闻
 * 
 * @param {string} username - 用户名（可选）
 * @returns {Object} 包含已下线新闻数据和状态的对象
 */
export const useSunsetNews = (username?: string) => {
  return useQuery({
    queryKey: [SUNSET_NEWS_KEY, username], // 以用户名为缓存键的一部分
    queryFn: () => getSunsetNews(username), // 调用API获取已下线新闻
  });
};

/**
 * 发布新闻Hook
 * 处理新闻发布操作
 * 
 * @returns {Object} mutation对象，包含执行方法和状态
 */
export const usePublishNews = () => {
  const queryClient = useQueryClient(); // 获取queryClient实例
  
  return useMutation({
    mutationFn: ({ id, publishTime }: { id: number | string, publishTime?: number }) => 
      publishNews(Number(id), publishTime ? { publishTime } : undefined), // 调用API发布新闻
    onSuccess: () => {
      // 成功后刷新相关列表
      queryClient.invalidateQueries({ queryKey: [UNPUBLISHED_NEWS_KEY] }); // 使待发布缓存失效
      queryClient.invalidateQueries({ queryKey: [PUBLISHED_NEWS_KEY] }); // 使已发布缓存失效
      queryClient.invalidateQueries({ queryKey: [NEWS_LIST_KEY] }); // 使新闻列表缓存失效
      message.success('发布成功'); // 显示成功消息
    },
    onError: (error: ApiError) => {
      // 显示错误消息
      message.error(error.response?.data?.message || error.message || '发布失败');
    }
  });
};

/**
 * 下线新闻Hook
 * 处理新闻下线操作
 * 
 * @returns {Object} mutation对象，包含执行方法和状态
 */
export const useUnpublishNews = () => {
  const queryClient = useQueryClient(); // 获取queryClient实例
  
  return useMutation({
    mutationFn: (id: number | string) => unpublishNews(Number(id)), // 调用API下线新闻
    onSuccess: (_, id) => {
      // 成功后刷新已发布和已下线列表
      queryClient.invalidateQueries({ queryKey: [PUBLISHED_NEWS_KEY] }); // 使已发布缓存失效
      queryClient.invalidateQueries({ queryKey: [SUNSET_NEWS_KEY] }); // 使已下线缓存失效
      queryClient.invalidateQueries({ queryKey: [NEWS_DETAIL_KEY, id] }); // 使新闻详情缓存失效
      message.success('新闻下线成功'); // 显示成功消息
    },
    onError: (error: ApiError) => {
      // 显示错误消息
      message.error(error.response?.data?.message || error.message || '下线新闻失败');
    }
  });
}; 